package com.gitee.qdbp.vmall.sales.biz.goods.manage.basic;

import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.model.condition.OrderWhere;
import com.gitee.qdbp.base.model.condition.Where;
import com.gitee.qdbp.general.common.api.sequence.service.ILocalSequenceGenerator;
import com.gitee.qdbp.tools.utils.JsonTools;
import com.gitee.qdbp.tools.utils.VerifyTools;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeBean;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeUpdate;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeWhere;
import com.gitee.qdbp.vmall.sales.biz.goods.manage.dao.IInventoryRealtimeBasicDao;

/**
 * 实时库存基础业务类
 *
 * @author zhh
 * @version 180626
 */
@Service
public class InventoryRealtimeBasic {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(InventoryRealtimeBasic.class);

    /** 序列号生成(ID) **/
    @Autowired
    private ILocalSequenceGenerator sequenceGenerator;

    /** 实时库存DAO **/
    @Autowired
    private IInventoryRealtimeBasicDao inventoryRealtimeBasicDao;

    /**
     * 实时库存查询
     *
     * @param where 查询条件
     * @return 实时库存
     * @throws ServiceException 查询失败
     */
    public InventoryRealtimeBean find(InventoryRealtimeWhere where) throws ServiceException {
        String msg = "Failed to query InventoryRealtime. ";

        if (where == null) {
            log.error(msg + "params is null: where");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        doHandleDate(where);

        InventoryRealtimeBean bean;
        try {
            bean = inventoryRealtimeBasicDao.find(Where.of(where));
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + "\n\t" + JsonTools.toJsonString(where), e);
            throw new ServiceException(ResultCode.DB_SELECT_ERROR, e);
        }

        if (bean == null) {
            log.trace("InventoryRealtime not found. {}", JsonTools.toJsonString(where));
        }
        return bean;
    }

    /**
     * 根据主键查询实时库存
     *
     * @param id 主键
     * @return 实时库存
     * @throws ServiceException 查询失败
     */
    public InventoryRealtimeBean findById(String id) throws ServiceException {
        String msg = "Failed to query InventoryRealtime by id. ";

        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        InventoryRealtimeWhere where = new InventoryRealtimeWhere();
        where.setId(id);

        return find(where);
    }

    /**
     * 实时库存查询
     *
     * @param paging 排序分页条件
     * @return 实时库存列表
     * @throws ServiceException 查询失败
     */
    public PageList<InventoryRealtimeBean> list(OrderPaging paging) throws ServiceException {
        String msg = "Failed to query InventoryRealtime. ";

        if (paging == null) {
            log.error(msg + "params is null: paging");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        return list(new InventoryRealtimeWhere(), paging);
    }

    /**
     * 实时库存查询
     *
     * @param where 查询条件
     * @param paging 排序分页条件
     * @return 实时库存列表
     * @throws ServiceException 查询失败
     */
    public PageList<InventoryRealtimeBean> list(InventoryRealtimeWhere where, OrderPaging paging) throws ServiceException {
        String msg = "Failed to query InventoryRealtime. ";

        if (paging == null) {
            log.error(msg + "params is null: paging");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        doHandleDate(where);

        try {
            OrderWhere<InventoryRealtimeWhere> ow = OrderWhere.of(where, paging.getOrderings());
            return PageList.of(inventoryRealtimeBasicDao.list(ow, paging));
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + "\n\t" + JsonTools.toJsonString(where), e);
            throw new ServiceException(ResultCode.DB_SELECT_ERROR, e);
        }
    }

    /**
     * 根据主键查询实时库存列表
     *
     * @param ids 主键列表
     * @return 实时库存列表
     * @throws ServiceException 查询失败
     */
    public PageList<InventoryRealtimeBean> listByIds(List<String> ids) throws ServiceException {
        String msg = "Failed to query InventoryRealtime by id list. ";

        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        InventoryRealtimeWhere where = new InventoryRealtimeWhere();
        where.setIds(ids);

        return list(where, OrderPaging.NONE);
    }

    /**
     * 创建实时库存
     *
     * @param model 待新增的实时库存
     * @return 受影响行数
     * @throws ServiceException 创建失败
     */
    public int create(InventoryRealtimeBean model) throws ServiceException {
        String msg = "Failed to create InventoryRealtime. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (VerifyTools.isBlank(model.getId())) {
            model.setId(sequenceGenerator.generate(InventoryRealtimeBean.TABLE));
        }

        doHandleDate(model);

        // 向vml_inventory_realtime表插入记录
        int rows;
        try {
            rows = inventoryRealtimeBasicDao.insert(model);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_INSERT_ERROR, e);
        }

        if (rows == 0) {
            log.error(msg + "affected rows is 0. \n\t" + JsonTools.toJsonString(model));
            throw new ServiceException(ResultCode.DB_INSERT_ERROR);
        }
        return rows;
    }

    /**
     * 批量创建实时库存
     *
     * @param models 待新增的实时库存
     * @return 受影响行数
     * @throws ServiceException 创建失败
     */
    public int create(List<InventoryRealtimeBean> models) throws ServiceException {
        String msg = "Failed to batch create InventoryRealtime. ";

        if (VerifyTools.isBlank(models)) {
            log.error(msg + "params is null: models");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        for (InventoryRealtimeBean model : models) {
            if (VerifyTools.isBlank(model.getId())) {
                model.setId(sequenceGenerator.generate(InventoryRealtimeBean.TABLE));
            }

            doHandleDate(model);
        }

        // 向vml_inventory_realtime表插入记录
        int rows;
        try {
            rows = inventoryRealtimeBasicDao.inserts(models);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(models), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(models), e);
            throw new ServiceException(ResultCode.DB_INSERT_ERROR, e);
        }

        int size = models.size();
        if (rows != size) {
            String desc = size > 0 ? "affected rows " + rows + "!=" + size + ". " : "affected rows is 0. ";
            log.error(msg + desc + "\n\t" + JsonTools.toJsonString(models));
            throw new ServiceException(ResultCode.DB_INSERT_ERROR);
        }
        return rows;
    }

    /**
     * 修改实时库存
     *
     * @param model 待修改的内容
     * @param errorOnUnaffected 受影响行数为0时是否抛异常
     * @return 受影响行数
     * @throws ServiceException 修改失败
     */
    public int update(InventoryRealtimeUpdate model, boolean errorOnUnaffected) throws ServiceException {
        String msg = "Failed to update InventoryRealtime. ";

        if (model == null) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (VerifyTools.isNotBlank(model.getId())) {
            if (model.getWhere() == null || VerifyTools.isBlank(model.getWhere().getId())) {
                model.getWhere(true).setId(model.getId());
            }
        }
        return doUpdate(model, 0, errorOnUnaffected);
    }

    /**
     * 根据主键删除实时库存
     *
     * @param ids 待删除的实时库存的主键
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    public int deleteByIds(List<String> ids, boolean errorOnRowsNotMatch) throws ServiceException {
        String msg = "Failed to delete InventoryRealtime. ";

        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        InventoryRealtimeWhere where = new InventoryRealtimeWhere();
        where.setIds(ids);

        return doDelete(where, ids.size(), errorOnRowsNotMatch);
    }

    /**
     * 根据条件删除实时库存
     *
     * @param where 条件
     * @param errorOnUnaffected 删除行数为0时是否抛异常
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    public int delete(InventoryRealtimeWhere where, boolean errorOnUnaffected) throws ServiceException {
        String msg = "Failed to delete InventoryRealtime. ";

        if (where == null) {
            log.error(msg + "params is null: where");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        return doDelete(where, 0, errorOnUnaffected);
    }

    /**
     * 根据条件删除实时库存
     *
     * @param where 条件
     * @param size 应删除条数, 0表示未知
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @param isId 是不是唯一主键
     * @return 删除行数
     * @throws ServiceException 删除失败
     */
    private int doDelete(InventoryRealtimeWhere where, int size, boolean errorOnRowsNotMatch) throws ServiceException {
        String msg = "Failed to delete InventoryRealtime. ";

        doHandleDate(where);

        int rows;
        try {
            rows = inventoryRealtimeBasicDao.delete(Where.of(where));
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + JsonTools.toJsonString(where), e);
            throw new ServiceException(ResultCode.DB_DELETE_ERROR, e);
        }

        if (size > 0 && rows != size || rows == 0) {
            String desc = size > 0 ? "affected rows != " + size + ". " : "affected rows is 0. ";
            if (errorOnRowsNotMatch) {
                log.error(msg + desc + "\n\t" + JsonTools.toJsonString(where));
                throw new ServiceException(ResultCode.DB_DELETE_ERROR);
            } else {
                log.debug(msg + desc + "\n\t" + JsonTools.toJsonString(where));
            }
        }
        return rows;
    }

    /**
     * 修改实时库存
     *
     * @param model 待修改的内容
     * @param size 应删除条数, 0表示未知
     * @param errorOnRowsNotMatch 删除行数不匹配时是否抛异常
     * @return 受影响行数
     * @throws ServiceException 修改失败
     */
    private int doUpdate(InventoryRealtimeUpdate model, int size, boolean errorOnRowsNotMatch) throws ServiceException {
        String msg = "Failed to update InventoryRealtime. ";

        if (model == null) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (model.getWhere() == null) {
            log.error(msg + "params is null: model.getWhere()");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        doHandleDate(model);
        doHandleDate(model.getWhere());

        int rows;
        try {
            rows = inventoryRealtimeBasicDao.update(model);
        } catch (DuplicateKeyException e) {
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_DUPLICATE_KEY, e);
        } catch (Exception e) {
            ServiceException.throwWhenServiceException(e);
            log.error(msg + e.getClass().getSimpleName() + ".\n\t" + JsonTools.toJsonString(model), e);
            throw new ServiceException(ResultCode.DB_UPDATE_ERROR, e);
        }

        if (size > 0 && rows != size || rows == 0) {
            String desc = size > 0 ? "affected rows != " + size + ". " : "affected rows is 0. ";
            if (errorOnRowsNotMatch) {
                log.error(msg + desc + "\n\t" + JsonTools.toJsonString(model));
                throw new ServiceException(ResultCode.DB_UPDATE_ERROR);
            } else {
                log.debug(msg + desc + "\n\t" + JsonTools.toJsonString(model));
            }
        }
        return rows;
    }

    // 由于数据库不支持毫秒, 超过500毫秒会因四舍五入导致变成下一天0点, 因此将毫秒清掉
    protected static void doHandleDate(InventoryRealtimeBean model) {
        if (model == null) {
            return;
        }

    }

    // 由于数据库不支持毫秒, 超过500毫秒会因四舍五入导致变成下一天0点, 因此将毫秒清掉
    // 处理XxxTime, XxxTimeMin和XxxTimeMax, XxxTimeMinWithDay和XxxTimeMaxWithDay
    protected static void doHandleDate(InventoryRealtimeWhere model) {
        if (model == null) {
            return;
        }


    }
}